home *** CD-ROM | disk | FTP | other *** search
- /*\
- * INTEL hex <-> binary file Converter.
- *
- * T.Bohning
- * 11851 NW 37 Place
- * Sunrise, FL 33323
- *
- * Compiler: Microsoft C 5.1
- * 2/20/89
- *
- * Compuserve User ID: [71036,1066]
- * GEnie address: T.BOHNING
- *
- INTEL hex description:
- 8 bit codes are split into two nibbles, and each nibble stored as
- a hex ascii digit '0' through 'F'.
- Each line of the intel hex file is a record, with the following format:
-
- :NNAAAATTD1D2D3D4....DnCC
-
- The colon means start of record, NN is the number of data bytes in the
- record given as two hex digits. AAAA is the starting load address of
- the record.
- *
- TT is a record type, 00 for data records. D1,D2...Dn are the hex ASCII
- representations of the data bytes. CC is a hex ASCII checksum, chosen
- such that the sum of all preceding byte values in the record
- (not just the data bytes) modulo 256 = 0.
- *
- The end of the hex file is marked by a record with a data length of 0
- and a record type of 1.
- *
- * This description is for "old" INTEL hex, which could only support
- * 64K loads. "Extended" INTEL hex was developed when the 8086 came
- * along.
- \*/
-
- #include <stdio.h>
- #include <string.h>
- #include <conio.h>
- #include <stdlib.h>
-
- enum bool { FALSE, TRUE };
-
- /*\
- * function prototypes
- \*/
- void genbin( FILE *inptr, FILE *outptr);
- void genhex( FILE *inptr, FILE *outptr);
- int getyn( char *msg );
- char get_hexbyte( char *cptr );
- int hexext( char *filename );
- void main( int argc, char *argv[] );
- char * put_hexbyte( char *cptr, char val );
- void read_exit( void );
- void usexit( void );
- void write_exit( void );
-
- /* file i/o buffer size (2 allocated)
- */
- #define FILE_BUFSIZE 0x6000
-
- void
- main( argc, argv)
- int argc;
- char *argv[]; {
- FILE *inptr, *outptr;
- int tohex; /* TRUE -> binary to HEX */
- char *inbuf, *outbuf; /* file I/O buffers */
-
- /*\
- * Check args.
- \*/
- if (argc != 3) {
- usexit();
- }
-
- /*\
- * Open files, check for .HEX extension, establish
- * conversion direction.
- \*/
- tohex = hexext(argv[2]) ? TRUE : (hexext(argv[1]) ? FALSE : usexit());
-
- /*\
- * Open the files.
- \*/
- if ( (inptr = fopen( argv[1], tohex ? "rb" : "rt" )) == NULL ) {
- printf("can't open %s for reading", argv[1]);
- }
-
- /*\
- * Test for output file existence first.
- \*/
- if ( (outptr = fopen( argv[2], "rb" )) != NULL ) {
-
- if ( getyn("Output file exists, overwrite (Y/N)? ") == 'N' ) {
- usexit();
- } else {
- fclose( outptr );
- }
- }
- if ( (outptr = fopen( argv[2], tohex ? "wt" : "wb" )) == NULL ) {
- printf("can't open %s for writing", argv[1]);
- }
-
- /*\
- * Allocate and set up file I/O buffers
- \*/
- if ( ( (inbuf = malloc( FILE_BUFSIZE)) == NULL)
- ||
- ( (outbuf = malloc( FILE_BUFSIZE)) == NULL) ) {
-
- puts("Can't allocate file I/O buffers");
- exit(1);
- }
- if ( setvbuf( inptr, inbuf, _IOFBF, FILE_BUFSIZE )
- ||
- setvbuf( outptr, outbuf, _IOFBF, FILE_BUFSIZE ) ) {
-
- puts("Error setting file buffers");
- exit(1);
- }
-
- printf("Converting: %s -> %s\n", argv[1], argv[2] );
- if (tohex) {
- genhex(inptr, outptr);
- } else {
- genbin(inptr, outptr);
- }
- }
- /*\
- * Print msg, Get y or n from user.
- * Return upper case variant.
- \*/
- int
- getyn( msg )
- char *msg; {
- int c;
-
- puts( msg );
-
- while( 1) {
- c = getche();
- puts("");
-
- if ( (c == 'y') || (c == 'Y') ) {
- return( 'Y' );
- }
- if ( (c == 'n') || (c == 'N') ) {
- return( 'N' );
- }
- }
- }
- /*\
- * Get a byte from hex ascii string, return the value.
- \*/
- char
- get_hexbyte( cptr )
- char *cptr; {
- char retval;
- char nbl;
- int shift;
-
- retval = 0;
-
- for( shift = 4; shift >= 0; shift -= 4 ) {
-
- if ((*cptr >= '0') && (*cptr <= '9')) {
- nbl = *cptr - '0';
- } else {
- if ((*cptr >= 'A') && (*cptr <= 'F')) {
- nbl = *cptr - 'A' + 10;
- } else {
- puts("Hex file contains invalid character");
- exit(1);
- }
- }
- ++cptr;
-
- retval |= (nbl << shift);
- }
- return( retval );
- }
- /*\
- * Convert INTEL hex at infile to binary at outfile.
- \*/
- void
- genbin( inptr, outptr)
- FILE *inptr, *outptr; {
- char linebuf[256]; /* input buffer */
- char c;
-
- char *bufptr;
- int numbytes;
- char chksum;
-
- int i;
-
- int linenum = 1;
-
- printf("Processing hex file line number: %5d", linenum );
-
- /*\
- * process input file 1 line at a time.
- \*/
- while( fgets( linebuf, sizeof(linebuf)-1, inptr) != NULL ) {
-
- chksum = 0;
-
- bufptr = linebuf;
-
- if ( *bufptr++ != ':' ) {
- printf("Intel hex format error in line %d\n", linenum);
- exit(1);
- }
-
- /*\
- * Get number of data bytes and add into checksum.
- \*/
- numbytes = get_hexbyte( bufptr );
- chksum += (char)numbytes;
- bufptr += 2;
-
- /*\
- * Add load address and record type into checksum.
- \*/
- for( i = 0; i < 3; ++i ) {
- chksum += get_hexbyte( bufptr );
- bufptr += 2;
- }
-
- /*\
- * Write the binary data.
- \*/
- for( i = 0; i < numbytes; ++i ) {
- c = get_hexbyte(bufptr);
- bufptr += 2;
-
- putc( c, outptr);
- chksum += c;
- }
-
- if ( ferror( outptr ) ) {
- write_exit();
- }
-
- /*\
- * Sum in checksum byte and check the sum.
- \*/
- chksum += get_hexbyte(bufptr);
- if (chksum != 0) {
- printf("Checksum error in line %d\n", linenum);
- exit(1);
- }
-
- if( numbytes == 0 ) {
- puts("");
- exit(0); /* end of hex file */
- }
-
- ++linenum;
- if ( (linenum & 0x3F) == 0 ) {
- printf("\b\b\b\b\b%5d", linenum);
- }
- }
-
- if (ferror(inptr)) {
- read_exit();
- }
-
- puts("\nWarning: Terminator record not found, hex file probably truncated.");
- exit(1);
- }
- /*\
- * Convert infile to INTEL hex at outfile.
- \*/
- void
- genhex( inptr, outptr)
- FILE *inptr, *outptr; {
-
- #define DATA_BYTES 0x10 /* data bytes per record */
-
- /* hex file line buffer, one space for a NULL,
- * one space for \n
- *
- : len addr 00 cks \n null */
- char hexline[ DATA_BYTES*2 + 1 + 2 + 4 + 2 + 2 + 1 + 1 ];
- char data_buf[ DATA_BYTES ];
-
- unsigned int load_addr = 0;
- int numbytes, i;
-
- unsigned char chksum;
- unsigned char *bufptr;
-
- unsigned int linenum = 1;
-
- hexline[0] = ':'; /* colon always starts a record */
- hexline[7] = '0'; /* type for data records is */
- hexline[8] = '0'; /* ... 00 */
-
- printf("Processing hex file line number: %5d", linenum );
-
- /*\
- * Build a line
- \*/
- while(
- (numbytes = fread( data_buf, sizeof(char), DATA_BYTES, inptr)) != 0
- ) {
-
- /*\
- * Write out all the bytes as hex,
- * updating chechksum as we go.
- \*/
- bufptr = &hexline[1]; /* skip the colon */
-
- chksum = (char)numbytes;
- bufptr = put_hexbyte( bufptr, (char)numbytes );
-
- chksum += (char)(load_addr >> 8);
- chksum += (char)load_addr;
-
- bufptr = put_hexbyte( bufptr, (char)(load_addr >> 8) );
- bufptr = put_hexbyte( bufptr, (char)load_addr );
-
- bufptr += 2; /* skip over data record type */
-
- /*\
- * Write out actual data bytes.
- \*/
- for(i = 0; i < numbytes; i++) {
- chksum += data_buf[i];
- bufptr = put_hexbyte( bufptr, data_buf[i] );
- }
-
- chksum = ~chksum+1;
- bufptr = put_hexbyte( bufptr, chksum );
-
- *bufptr++ = '\n';
- *bufptr = NULL;
-
- /*\
- * write this line of the hex file
- \*/
- fputs( hexline, outptr );
-
- if ( ferror(outptr) ) {
- write_exit();
- }
-
- load_addr += numbytes;
-
- ++linenum;
- if ( (linenum & 0x3F) == 0 ) {
- printf("\b\b\b\b\b%5d", linenum);
- }
- }
- puts("");
-
- if ( ferror(inptr) ) {
- read_exit();
- }
-
- fputs(":00000001FF", outptr); /* Standard termination record */
- }
- /*\
- * Try to find .HEX extension on a filename.
- \*/
- hexext( cptr )
- char *cptr; {
-
- return( !strcmpi( cptr + strlen(cptr) - 4, ".hex") );
- }
- /*\
- * Put a byte as hex ascii, return pointer to next location.
- \*/
- char *
- put_hexbyte(cptr, val)
- char *cptr;
- char val; {
- static char hextbl[16] = {
- '0', '1', '2', '3', '4', '5', '6', '7',
- '8', '9', 'A', 'B', 'C', 'D', 'E', 'F'
- };
-
- *cptr++ = hextbl[ ((val >> 4) & 0x0F) ];
-
- *cptr++ = hextbl[ val & 0x0F ];
-
- return(cptr);
- }
- /*\
- * read error on input file
- \*/
- void
- read_exit() {
- puts("Error on input file read");
- exit(1);
- }
- /*\
- * Show usage and die.
- \*/
- void
- usexit() {
- puts("\nINTEL hex <-> binary file converter");
- puts("\nUsage: HEXBIN infile outfile" );
- puts("\nEither infile or outfile must have .HEX extension");
-
- puts("\nIf infile has .HEX extension, HEX to binary conversion is performed");
- puts("If outfile has .HEX extension, binary to HEX conversion is performed");
-
- exit(1);
- }
- /*\
- * write error on output file
- \*/
- void
- write_exit() {
- puts("Error on output file write");
- exit(1);
- }
- /************************ EOF *************************/